package com.cw.base.common.dispatch.pojo;

import com.cw.base.common.dispatch.enums.EnumModuleCode;
import com.cw.base.common.dispatch.enums.EnumServiceScene;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.hibernate.validator.constraints.Length;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Date;

/**
 * 公共请求报文
 *
 * @author chenw
 * @version $$Id: BaseReqDto.java, v 0.1 2018/9/19 上午11:11 chenw Exp $$
 */
@Data
@ApiModel(value = "BaseReqDto", description = "公共请求报文")
public class BaseReqDto implements Serializable {

    /** serialVersionUID */
    private static final long serialVersionUID = -1452554375506451535L;

    /**
     * 请求模块
     */
    @NotNull(message = "请求模块不能为空")
    @ApiModelProperty(value = "请求模块")
    private EnumModuleCode ask;

    /**
     * 响应模块
     */
    @NotNull(message = "响应模块不能为空")
    @ApiModelProperty(value = "响应模块")
    private EnumModuleCode answer;

    /**
     * 统一渠道流水号
     */
    @NotBlank(message = "统一渠道流水号不能为空")
    @Length(max = 40, message = "统一渠道流水号最长40位")
    @ApiModelProperty(value = "统一渠道流水号")
    private String serialNo;

    /**
     * 幂等流水号（默认可以使用统一的统一渠道流水号）
     */
    @NotNull(message = "幂等流水号不能为空")
    @Length(max = 40, message = "幂等流水号最长40位")
    @ApiModelProperty(value = "幂等流水号")
    private String idemSerialNo;

    /**
     * 服务场景
     */
    @NotNull(message = "服务场景不能为空")
    @ApiModelProperty(value = "服务场景")
    private EnumServiceScene serviceScene;

    /**
     * 交易日期时间
     */
    @NotNull(message = "交易日期时间不能为空")
    @ApiModelProperty(value = "交易日期时间")
    private Date transDateTime;

    /**
     * 渠道标示 (需要渠道管理动态配置）
     */
    @NotBlank(message = "渠道标示不能为空")
    @Length(max = 40, message = "渠道标示最长不能超过40位")
    @ApiModelProperty(value = "渠道标示")
    private String channelNo;

    /**
     * 签名-UUID 用于系统发放的TOKEN验证，比如管理台发放的TOKEN、门户发放的TOKEN、APP发放的TOKEN，原则粒度是在租户下的渠道支持控制
     */
    @ApiModelProperty(value = "签名")
    private String sign;

    public static final class Builder {

        private BaseReqDto instance = new BaseReqDto();

        private Builder() {}

        /**
         * 获取实例
         *
         * @return {@link Builder}
         */
        public static Builder getInstance() {
            return new Builder();
        }

        /**
         * 获取实例
         *
         * @param instance 原实例
         * @return {@link Builder}
         */
        public static Builder getInstance(BaseReqDto instance) {
            Builder builder = new Builder();
            builder.instance = instance;
            return builder;
        }

        /**
         * 添加参数
         *
         * @param ask 参数
         * @return {@link Builder}
         */
        public Builder addAsk(EnumModuleCode ask) {
            this.instance.setAsk(ask);
            return this;
        }

        /**
         * 添加参数
         *
         * @param answer 参数
         * @return {@link Builder}
         */
        public Builder addAnswer(EnumModuleCode answer) {
            this.instance.setAnswer(answer);
            return this;
        }

        /**
         * 添加参数
         *
         * @param serialNo 参数
         * @return {@link Builder}
         */
        public Builder addSerialNo(String serialNo) {
            this.instance.setSerialNo(serialNo);
            return this;
        }

        /**
         * 添加参数
         *
         * @param idemSerialNo 参数
         * @return {@link Builder}
         */
        public Builder addIdemSerialNo(String idemSerialNo) {
            this.instance.setIdemSerialNo(idemSerialNo);
            return this;
        }

        /**
         * 添加参数
         *
         * @param serviceScene 参数
         * @return {@link Builder}
         */
        public Builder addServiceScene(EnumServiceScene serviceScene) {
            this.instance.setServiceScene(serviceScene);
            return this;
        }

        /**
         * 添加参数
         *
         * @param transDateTime 参数
         * @return {@link Builder}
         */
        public Builder addTransDateTime(Date transDateTime) {
            this.instance.setTransDateTime(transDateTime);
            return this;
        }

        /**
         * 添加参数
         *
         * @param channelNo 参数
         * @return {@link Builder}
         */
        public Builder addChannelNo(String channelNo) {
            this.instance.setChannelNo(channelNo);
            return this;
        }

        /**
         * 添加参数
         *
         * @param sign 参数
         * @return {@link Builder}
         */
        public Builder addSign(String sign) {
            this.instance.setSign(sign);
            return this;
        }

        /**
         * 生成实例
         *
         * @return {@link BaseReqDto}
         */
        public BaseReqDto build() {
            return this.instance;
        }
    }

    /**
     * 相当于深拷贝出一个全新的{@link BaseReqDto}对象
     *
     * @return 全新的 {@link BaseReqDto}对象
     */
    public BaseReqDto copy() {
        return Builder.getInstance()
            .addTransDateTime(getTransDateTime())
            .addSign(getSign())
            .addServiceScene(getServiceScene())
            .addSerialNo(getSerialNo())
            .addIdemSerialNo(getIdemSerialNo())
            .addChannelNo(getChannelNo())
            .addAsk(getAsk())
            .addAnswer(getAnswer())
            .build();
    }

}
